/*
 * @Date: 2020-09-19 09:31:30
 * @LastEditors: 小枫
 * @LastEditTime: 2020-09-19 12:54:24
 * @FilePath: \vue3-camp\server.js
 */
const fs = require('fs')
const path = require('path')
const Koa = require('koa')
const compilerSfc = require('@vue/compiler-sfc');
const compilerDom = require('@vue/compiler-dom')

const app = new Koa()

/**
 * @description: 把不是./ ../开头的替换为/@modules/
 * @param {string} 
 * @return {string} 
 */
function rewriteImport(content) {
  return content.replace(/ from ['|"]([^'"]+)['|"]/g, function (s0, s1) {
    if (s1[0] !== '.' && s1[1] !== '/') {
      return ` from '/@modules/${s1}'`
    } else {
      return s0
    }
  })
}

app.use(ctx => {
  const { request: { url, query } } = ctx
  if (url === "/") {
    let content = fs.readFileSync('./index.html', 'utf-8')
    // 注入一个socket客户端
    // 后端的文件变了，通知前端去更新
    content = content.replace('<script', `
      <script>
        window.process = {
          env: {NODE_EV:'dev'}
        }
      </script>
      <script
    
    `)
    ctx.type = "text/html"
    ctx.body = content
  } else if (url.endsWith('.js')) {
    const p = path.resolve(__dirname, url.slice(1))
    ctx.type = 'application/javascript'
    const content = fs.readFileSync(p, 'utf-8')
    ctx.body = rewriteImport(content)
  } else if (url.startsWith('/@modules/')) {
    const prefix = path.resolve(__dirname, 'node_modules', url.replace('/@modules/', ''))
    const module = require(prefix + '/package.json').module
    const p = path.resolve(prefix, module)
    const ret = fs.readFileSync(p, 'utf-8')
    ctx.type = 'application/javascript'
    ctx.body = rewriteImport(ret)
  } else if (url.indexOf('.vue') > -1) {
    // 解析单文件
    const p = path.resolve(__dirname, url.split('?')[0].slice(1))
    // 使用官方库解析单文件
    const { descriptor } = compilerSfc.parse(fs.readFileSync(p, 'utf-8'))
    // console.log(descriptor);
    if (!query.type) {
      ctx.type = 'application/javascript'
      ctx.body = `
      ${rewriteImport(descriptor.script.content.replace('export default ', 'const __script = '))}
      import { render as __render } from "${url}?type=template"
      __script.render = __render
      export default __script
      `
    } else if (query.type == "template") {
      // 解析我们的template 变成render函数
      const template = descriptor.template
      const render = compilerDom.compile(template.content, { mode: "module" }).code
      ctx.type = 'application/javascript'
      ctx.body = rewriteImport(render)
    }
  }
})

app.listen(9000, () => {
  console.log('listened to 9000');
})
